﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RaytracerLib.MathLib;
using YAXLib;
using System.Diagnostics;

namespace RaytracerLib.Attenuations
{
    public class PolynomialAttenuation : Attenuation
    {
        /// <summary>
        /// Spherical.
        /// </summary>
        [YAXNode]
        public ColorFloat A;

        /// <summary>
        /// Linear.
        /// </summary>
        [YAXNode]
        public ColorFloat B;

        /// <summary>
        /// Constant.
        /// </summary>
        [YAXNode]
        public ColorFloat C;

        private ColorFloat m_real_a;
        private ColorFloat m_real_b;

        public PolynomialAttenuation()
        {
        }

        public PolynomialAttenuation(ColorFloat a_a, ColorFloat a_b, ColorFloat a_c)
        {
            Debug.Assert(a_a >= ColorFloat.Black);
            Debug.Assert(a_b >= ColorFloat.Black);
            Debug.Assert(a_c >= ColorFloat.White);

            A = a_a;
            B = a_b;
            C = a_c;
        }

        public override ColorFloat Attenuate(ColorFloat a_light, double a_dist)
        {
            return a_light / (m_real_a * a_dist * a_dist + m_real_b * a_dist + C);
        }

        public override void CalculateAttenuation(double a_light_speed)
        {
            Debug.Assert(A >= ColorFloat.Black);
            Debug.Assert(B >= ColorFloat.Black);
            Debug.Assert(C >= ColorFloat.White);

            m_real_a = A / a_light_speed / a_light_speed;
            m_real_b = B / a_light_speed;
        }

        public override bool Equals(object a_obj)
        {
            if (Object.ReferenceEquals(a_obj, this))
                return true;

            PolynomialAttenuation att = a_obj as PolynomialAttenuation;
            if (att == null)
                return false;

            return A.IsAlmostRelativeEquals(att.A) &&
                   B.IsAlmostRelativeEquals(att.B) &&
                   C.IsAlmostRelativeEquals(att.C);
        }

        public override int GetHashCode()
        {
            return A.GetHashCode() ^ B.GetHashCode() ^ C.GetHashCode();
        }
    }
}
